/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package TimeRecording.tables;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.Embeddable;
import javax.persistence.Transient;

/**
 *
 * @author david
 */
@Embeddable
public class AllocationOfHours implements Serializable, Cloneable {

    public static final double ZERO_TIME = 0.000000001;
    
    // <editor-fold defaultstate="collapsed" desc="Property Change Support">
    @Transient
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

    public void addPropertyChangeListener(PropertyChangeListener listener) {
	changeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
	changeSupport.removePropertyChangeListener(listener);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Headline Properties">
    private double clocked;
    private double entered;
    private double sickness;
    private double holiday;
    private double estimated;

    public double getClocked() {
        return clocked;
    }

    public void setClocked(double value) {
        double oldValue = this.clocked;
        this.clocked = value;
        changeSupport.firePropertyChange("clocked", oldValue, value);
    }

    public double getEntered() {
        return entered;
    }

    public void setEntered(double value) {
        double oldValue = this.entered;
        this.entered = value;
        changeSupport.firePropertyChange("entered", oldValue, value);
    }

    public double getSickness() {
        return sickness;
    }

    public void setSickness(double value) {
        double oldValue = this.clocked;
        this.sickness = value;
        changeSupport.firePropertyChange("sickness", oldValue, value);
    }

    public double getHoliday() {
        return holiday;
    }

    public void setHoliday(double value) {
        double oldValue = this.clocked;
        this.holiday = value;
        changeSupport.firePropertyChange("holiday", oldValue, value);
    }

    public double getEstimated() {
        return estimated;
    }

    public void setEstimated(double value) {
        double oldValue = this.estimated;
        this.estimated = value;
        changeSupport.firePropertyChange("estimated", oldValue, value);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Fixed Pattern Properties">
    private double fixedExpected;
    private double fixedRecorded;
    private double fixedSickness;
    private double fixedHoliday;

    public double getFixedExpected() {
        return fixedExpected;
    }

    public void setFixedExpected(double value) {
        double oldExpected = this.getExpected();
        double oldValue = this.fixedExpected;
        this.fixedExpected = value;
        changeSupport.firePropertyChange("fixedExpected", oldValue, value);
        changeSupport.firePropertyChange("expected", oldExpected, getExpected());
    }

    public double getFixedRecorded() {
        return fixedRecorded;
    }

    public void setFixedRecorded(double value) {
        double oldRecorded = this.getRecorded();
        double oldValue = this.fixedRecorded;
        this.fixedRecorded = value;
        changeSupport.firePropertyChange("fixedRecorded", oldValue, value);
        changeSupport.firePropertyChange("recorded", oldRecorded, getRecorded());
    }

    public double getFixedSickness() {
        return fixedSickness;
    }

    public void setFixedSickness(double value) {
        double oldValue = this.fixedSickness;
        this.fixedSickness = value;
        changeSupport.firePropertyChange("fixedSickness", oldValue, value);
    }

    public double getFixedHoliday() {
        return fixedHoliday;
    }

    public void setFixedHoliday(double value) {
        double oldValue = this.fixedHoliday;
        this.fixedHoliday = value;
        changeSupport.firePropertyChange("fixedHoliday", oldValue, value);
    }

    public double getFixedShortfall() {
        return fixedExpected - fixedRecorded;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="SemiFlexi Pattern Properties">
    private double semiFlexiExpected;
    private double semiFlexiRecorded;
    private double semiFlexiSickness;
    private double semiFlexiHoliday;

    public double getSemiFlexiExpected() {
        return semiFlexiExpected;
    }

    public void setSemiFlexiExpected(double value) {
        double oldExpected = this.getExpected();
        double oldValue = this.semiFlexiExpected;
        this.semiFlexiExpected = value;
        changeSupport.firePropertyChange("semiFlexiExpected", oldValue, value);
        changeSupport.firePropertyChange("expected", oldExpected, getExpected());
    }

    public double getSemiFlexiRecorded() {
        return semiFlexiRecorded;
    }

    public void setSemiFlexiRecorded(double value) {
        double oldRecorded = this.getRecorded();
        double oldValue = this.semiFlexiRecorded;
        this.semiFlexiRecorded = value;
        changeSupport.firePropertyChange("semiFlexiRecorded", oldValue, value);
        changeSupport.firePropertyChange("recorded", oldRecorded, getRecorded());
    }

    public double getSemiFlexiSickness() {
        return semiFlexiSickness;
    }

    public void setSemiFlexiSickness(double value) {
        double oldValue = this.semiFlexiSickness;
        this.semiFlexiSickness = value;
        changeSupport.firePropertyChange("semiFlexiSickness", oldValue, value);
    }

    public double getSemiFlexiHoliday() {
        return semiFlexiHoliday;
    }

    public void setSemiFlexiHoliday(double value) {
        double oldValue = this.semiFlexiHoliday;
        this.semiFlexiHoliday = value;
        changeSupport.firePropertyChange("semiFlexiHoliday", oldValue, value);
    }

    public double getSemiFlexiShortfall() {
        return semiFlexiExpected - semiFlexiRecorded;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Flexi Pattern Properties">
    private double flexiExpected;
    private double flexiRecorded;
    private double flexiSickness;
    private double flexiHoliday;

    public double getFlexiExpected() {
        return flexiExpected;
    }

    public void setFlexiExpected(double value) {
        double oldExpected = this.getExpected();
        double oldValue = this.flexiExpected;
        this.flexiExpected = value;
        changeSupport.firePropertyChange("flexiExpected", oldValue, value);
        changeSupport.firePropertyChange("expected", oldExpected, getExpected());
    }

    public double getFlexiRecorded() {
        return flexiRecorded;
    }

    public void setFlexiRecorded(double value) {
        double oldRecorded = this.getRecorded();
        double oldValue = this.flexiRecorded;
        this.flexiRecorded = value;
        changeSupport.firePropertyChange("flexiRecorded", oldValue, value);
        changeSupport.firePropertyChange("recorded", oldRecorded, getRecorded());
    }

    public double getFlexiSickness() {
        return flexiSickness;
    }

    public void setFlexiSickness(double value) {
        double oldValue = this.flexiSickness;
        this.flexiSickness = value;
        changeSupport.firePropertyChange("flexiSickness", oldValue, value);
    }

    public double getFlexiHoliday() {
        return flexiHoliday;
    }

    public void setFlexiHoliday(double value) {
        double oldValue = this.flexiHoliday;
        this.flexiHoliday = value;
        changeSupport.firePropertyChange("flexiHoliday", oldValue, value);
    }

    public double getFlexiCredit() {
        return flexiRecorded - flexiExpected;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Sessional Pattern Properties">
    private double sessionExpected;
    private double sessionRecorded;
    private double sessionSickness;
    private double sessionHoliday;

    public double getSessionExpected() {
        return sessionExpected;
    }

    public void setSessionExpected(double value) {
        double oldExpected = this.getExpected();
        double oldValue = this.sessionExpected;
        this.sessionExpected = value;
        changeSupport.firePropertyChange("sessionExpected", oldValue, value);
        changeSupport.firePropertyChange("expected", oldExpected, getExpected());
    }

    public double getSessionRecorded() {
        return sessionRecorded;
    }

    public void setSessionRecorded(double value) {
        double oldRecorded = this.getRecorded();
        double oldValue = this.sessionRecorded;
        this.sessionRecorded = value;
        changeSupport.firePropertyChange("sessionRecorded", oldValue, value);
        changeSupport.firePropertyChange("recorded", oldRecorded, getRecorded());
    }

    public double getSessionSickness() {
        return sessionSickness;
    }

    public void setSessionSickness(double value) {
        double oldValue = this.sessionSickness;
        this.sessionSickness = value;
        changeSupport.firePropertyChange("sessionSickness", oldValue, value);
    }

    public double getSessionHoliday() {
        return sessionHoliday;
    }

    public void setSessionHoliday(double value) {
        double oldValue = this.sessionHoliday;
        this.sessionHoliday = value;
        changeSupport.firePropertyChange("sessionHoliday", oldValue, value);
    }

    public double getSessionCredit() {
        return sessionRecorded - sessionExpected;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Ad Hoc Pattern Properties">
    private double adHocRecorded;
    private double adHocSickness;
    private double adHocHoliday;

    public double getAdHocRecorded() {
        return adHocRecorded;
    }

    public void setAdHocRecorded(double value) {
        double oldRecorded = this.getRecorded();
        double oldValue = this.adHocRecorded;
        this.adHocRecorded = value;
        changeSupport.firePropertyChange("adHocRecorded", oldValue, value);
        changeSupport.firePropertyChange("recorded", oldRecorded, getRecorded());
    }

    public double getAdHocSickness() {
        return adHocSickness;
    }

    public void setAdHocSickness(double value) {
        double oldValue = this.adHocSickness;
        this.adHocSickness = value;
        changeSupport.firePropertyChange("adHocSickness", oldValue, value);
    }

    public double getAdHocHoliday() {
        return adHocHoliday;
    }

    public void setAdHocHoliday(double value) {
        double oldValue = this.adHocHoliday;
        this.adHocHoliday = value;
        changeSupport.firePropertyChange("adHocHoliday", oldValue, value);
    }
    // </editor-fold>

    public Double getExpected() {
        return fixedExpected + semiFlexiExpected + flexiExpected + sessionExpected;
    }

    public Double getRecorded() {
        return fixedRecorded + semiFlexiRecorded + flexiRecorded + sessionRecorded + adHocRecorded;
    }

    public void add(AllocationOfHours other) {

        this.entered += other.entered;
        this.clocked += other.clocked;
        this.sickness += other.sickness;
        this.holiday += other.holiday;

        this.fixedExpected += other.fixedExpected;
        this.fixedRecorded += other.fixedRecorded;
        this.fixedSickness += other.fixedSickness;
        this.fixedHoliday += other.fixedHoliday;

        this.semiFlexiExpected += other.semiFlexiExpected;
        this.semiFlexiRecorded += other.semiFlexiRecorded;
        this.semiFlexiSickness += other.semiFlexiSickness;
        this.semiFlexiHoliday += other.semiFlexiHoliday;

        this.flexiExpected += other.flexiExpected;
        this.flexiRecorded += other.flexiRecorded;
        this.flexiSickness += other.flexiSickness;
        this.flexiHoliday += other.flexiHoliday;

        this.sessionExpected += other.sessionExpected;
        this.sessionRecorded += other.sessionRecorded;
        this.sessionSickness += other.sessionSickness;
        this.sessionHoliday += other.sessionHoliday;

        this.adHocRecorded += other.adHocRecorded;
        this.adHocSickness += other.adHocSickness;
        this.adHocHoliday += other.adHocHoliday;
    }

    public void subtract(AllocationOfHours other) {

        this.entered -= other.entered;
        this.clocked -= other.clocked;
        this.sickness -= other.sickness;
        this.holiday -= other.holiday;

        this.fixedExpected -= other.fixedExpected;
        this.fixedRecorded -= other.fixedRecorded;
        this.fixedSickness -= other.fixedSickness;
        this.fixedHoliday -= other.fixedHoliday;

        this.semiFlexiExpected -= other.semiFlexiExpected;
        this.semiFlexiRecorded -= other.semiFlexiRecorded;
        this.semiFlexiSickness -= other.semiFlexiSickness;
        this.semiFlexiHoliday -= other.semiFlexiHoliday;

        this.flexiExpected -= other.flexiExpected;
        this.flexiRecorded -= other.flexiRecorded;
        this.flexiSickness -= other.flexiSickness;
        this.flexiHoliday -= other.flexiHoliday;

        this.sessionExpected -= other.sessionExpected;
        this.sessionRecorded -= other.sessionRecorded;
        this.sessionSickness -= other.sessionSickness;
        this.sessionHoliday -= other.sessionHoliday;

        this.adHocRecorded -= other.adHocRecorded;
        this.adHocSickness -= other.adHocSickness;
        this.adHocHoliday -= other.adHocHoliday;
    }

    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(AllocationOfHours.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    @Override
    public String toString() {
        return "AllocationOfHours{" + "clocked=" + clocked +
                "entered=" + entered +
                "sickness=" + sickness +
                "holiday=" + holiday +
                "estimated=" + estimated + '}';
    }
}
